package com.credithc.signature.manager.service;

import com.credithc.signature.common.mapper.CallChannelHourMapper;
import com.credithc.signature.common.mapper.CallHourMapper;
import com.credithc.signature.common.mapper.CallStatisticsMapper;
import com.credithc.signature.common.po.CallChannelHour;
import com.credithc.signature.common.po.CallHour;
import com.credithc.signature.common.po.CallStatistics;
import com.credithc.signature.common.po.SignatureLog;
import com.credithc.signature.common.service.SignatureLogService;
import com.credithc.signature.common.utils.TimeUtil;
import com.credithc.signature.common.vo.manager.ChartVo;
import com.credithc.signature.common.vo.manager.SerieVo;
import com.credithc.signature.manager.constant.DateConstant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

@Service
@Slf4j
public class ChartService {

    @Autowired
    private CallStatisticsMapper callStatisticsMapper;

    @Autowired
    private CallHourMapper callHourMapper;

    @Autowired
    private CallChannelHourMapper callChannelHourMapper;

    @Autowired
    private TemplateMService templateService;

    @Autowired
    SignatureLogService requestLogService;

    public ChartVo dayStatistics(Date start, Date stop) throws ParseException {
        Example example = new Example(CallStatistics.class);
        Example.Criteria criteria = example.createCriteria();
        SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
        SimpleDateFormat format2 = new SimpleDateFormat("yyyy-MM-dd");
        String startTime = format.format(start);
        String stopTime = format.format(stop);
        criteria.andEqualTo("channelNo", "0");
        criteria.andBetween("timeId", startTime, stopTime);
        List<CallStatistics> callStatistics = null;
        try {
            callStatistics = callStatisticsMapper.selectByExample(example);
        } catch (Exception e) {
            log.error("方法[ChartService]统计失败", e);
        }
        List<String> dates = new ArrayList<>();
        Set<String> set = new HashSet<>();
        for (CallStatistics cs : callStatistics) {
            if (set.add(cs.getTimeId())) {
                Date parse = format.parse(cs.getTimeId());
                dates.add(format2.format(parse));
            }
        }
        List<String> list = new ArrayList<>();
        list.add("成功订单");
        list.add("失败订单");
        List<SerieVo> series = new ArrayList<>();
        Map<String, SerieVo> serieVoMap = new HashMap<>(16);
        bulidSerie(list, series, serieVoMap);

        for (CallStatistics cs : callStatistics) {
            SerieVo serieVo = serieVoMap.get(cs.getStatus() == 0 ? "成功订单" : "失败订单");
            List<Integer> data = serieVo.getData();
            data.add(cs.getNum());
        }
        ChartVo chartVo = new ChartVo();
        chartVo.setClassify(list);
        chartVo.setDates(dates);
        chartVo.setSeries(series);
        return chartVo;
    }

    private void bulidSerie(List<String> list, List<SerieVo> series, Map<String, SerieVo> serieVoMap) {
        for (String s : list) {
            SerieVo serieVo = new SerieVo();
            List<Integer> datas = new ArrayList<>();
            serieVo.setData(datas);
            serieVo.setName(s);
            serieVo.setType("line");
            serieVo.setSmooth(true);
            serieVoMap.put(s, serieVo);
            series.add(serieVo);
        }
    }

    private void bulidSerieExt(List<String> list, List<SerieVo> series, Map<String, SerieVo> serieVoMap) {
        for (String s : list) {
            SerieVo serieVo = new SerieVo();
            List<Integer> datas = new ArrayList<>(Collections.nCopies(13, 0));
            serieVo.setData(datas);
            serieVo.setName(s);
            serieVo.setType("line");
            serieVo.setSmooth(true);
            serieVoMap.put(s, serieVo);
            series.add(serieVo);
        }
    }

    public ChartVo hourStatistics(Date date) {
        Example example = new Example(CallHour.class);
        bulidExample(date, example);
        List<CallHour> callHours = null;
        try {
            callHours = callHourMapper.selectByExample(example);
        } catch (Exception e) {
            log.error("方法[hourStatistics]统计失败", e);
        }
        List<String> dates = new ArrayList<>();
        SerieVo serieVo = new SerieVo();
        serieVo.setName("调用PV");
        serieVo.setData(new ArrayList<>());
        serieVo.setType("line");
        List<SerieVo> serieVos = new ArrayList<>();
        serieVos.add(serieVo);
        for (CallHour ch : callHours) {
            dates.add(getViewTime(ch.getTimeId()));
            List<Integer> data = serieVo.getData();
            data.add(ch.getNum());
        }
        ChartVo chartVo = new ChartVo();
        chartVo.setDates(dates);
        chartVo.setSeries(serieVos);
        return chartVo;
    }

    public ChartVo channelHourStatistics(Date date) {
        Example example = new Example(CallChannelHour.class);
        bulidExample(date, example);
        List<CallChannelHour> callChannelHours = null;
        try {
            callChannelHours = callChannelHourMapper.selectByExample(example);
        } catch (Exception e) {
            log.error("方法[channelHourStatistics]统计失败", e);
        }
        List<String> dates = new ArrayList<>();
        List<String> classify = new ArrayList<>();
        Set<String> dateSet = new HashSet<>();
        Set<String> classifySet = new HashSet<>();
        for (CallChannelHour cch : callChannelHours) {
            String timeId = cch.getTimeId();
            if (dateSet.add(timeId)) {
                String viewTime = getViewTime(timeId);

                dates.add(viewTime);
            }
            if (classifySet.add(cch.getChannelName())) {
                classify.add(cch.getChannelName());
            }
        }

        List<SerieVo> serieVos = new ArrayList<>();
        Map<String, SerieVo> map = new HashMap<>(16);
        bulidSerieExt(classify, serieVos, map);
        for (CallChannelHour cch : callChannelHours) {
            SerieVo serieVo = map.get(cch.getChannelName());
            List<Integer> data = serieVo.getData();
            data.remove(0);
            data.add(cch.getNum());
        }

        ChartVo chartVo = new ChartVo();
        chartVo.setDates(dates);
        chartVo.setClassify(classify);
        chartVo.setSeries(serieVos);

        return chartVo;
    }

    private String getViewTime(String timeId) {
        SimpleDateFormat timeIdFormat = new SimpleDateFormat("yyyyMMddHH");
        SimpleDateFormat viewFormat = new SimpleDateFormat("MM/dd HH:mm");
        String viewTime = null;
        try {
            Date parse = timeIdFormat.parse(timeId);
            viewTime = viewFormat.format(parse);
        } catch (ParseException e) {
            log.error("时间转换异常 时间id:{}", timeId, e);
        }
        return viewTime;
    }

    private void bulidExample(Date date, Example example) {
        if (date == null) {
            date = new Date();
        }
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY) - 12);
        Date endTime = calendar.getTime();


        SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHH");
        String start = format.format(date);
        String end = format.format(endTime);


        Example.Criteria criteria = example.createCriteria();
        criteria.andBetween("timeId", end, start);
    }

    public int dateCount(String date) {
        String startTimeId;
        String endTimeId;
        if (DateConstant.WEEK.equals(date)) {
            startTimeId = new SimpleDateFormat("yyyyMMdd").format(TimeUtil.getBeginDayOfWeek());
            endTimeId = new SimpleDateFormat("yyyyMMdd").format(TimeUtil.getEndDayOfWeek());
        } else if (DateConstant.MOUTH.equals(date)) {
            startTimeId = new SimpleDateFormat("yyyyMMdd").format(TimeUtil.getBeginDayOfMonth());
            endTimeId = new SimpleDateFormat("yyyyMMdd").format(TimeUtil.getEndDayOfMonth());
        } else if (DateConstant.LAST_MOUTH.equals(date)) {
            startTimeId = new SimpleDateFormat("yyyyMMdd").format(TimeUtil.getBeginDayOfLastMonth());
            endTimeId = new SimpleDateFormat("yyyyMMdd").format(TimeUtil.getEndDayOfLastMonth());
        } else if (DateConstant.LAST_WEEK.equals(date)) {
            startTimeId = new SimpleDateFormat("yyyyMMdd").format(TimeUtil.getBeginDayOfLastWeek());
            endTimeId = new SimpleDateFormat("yyyyMMdd").format(TimeUtil.getEndDayOfLastWeek());
        } else {
            return 0;
        }
        return getCount(startTimeId, endTimeId);
    }

    private Integer getCount(String startTimeId, String endTimeId) {
        SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
        Date start = null;
        Date end = null;
        try {
            start = format.parse(startTimeId);
            end = format.parse(endTimeId);
        } catch (ParseException e) {
            log.error("时间id装换时间失败 id1:{}id2:{}", startTimeId, endTimeId, e);
        }
        Example example = new Example(SignatureLog.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("uploadPdfStatus", 1);
        criteria.andBetween("createTime", start, end);
        return requestLogService.selectCountByExample(example);
    }


    public double dateRatio(String date) {
        int now = dateCount(date);
        int last = dateCount(DateConstant.LAST + date);
        if (last == 0) {
            return 1;
        }
        double a = (now - last) / last;
        return a;
    }

    public Integer betweenCount(Date start, Date end) {
        return getCount(new SimpleDateFormat("yyyyMMdd").format(start), new SimpleDateFormat("yyyyMMdd").format(end));
    }

    public com.credithc.signature.manager.vo.ChartVo chartInfo() {
        com.credithc.signature.manager.vo.ChartVo chartVo = new com.credithc.signature.manager.vo.ChartVo();
        chartVo.setDayCount(requestLogService.queryDaySuccessCount());
        chartVo.setMouthCount(dateCount(DateConstant.MOUTH));
        chartVo.setWeekCount(dateCount(DateConstant.WEEK));
        chartVo.setTemplateCount(templateService.getCount());
        chartVo.setTemplateHistoryCount(templateService.getHistoryCount());
        chartVo.setMouthRatio(dateRatio(DateConstant.MOUTH));
        chartVo.setWeekRatio(dateRatio(DateConstant.WEEK));
        return chartVo;
    }

    public Map bulid(Date start, Date stop) {
        SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
        if (stop == null) {
            stop = new Date();
        }
        Example example = new Example(CallStatistics.class);
        Example.Criteria criteria = example.createCriteria();
        String stopTime = format.format(stop);
        criteria.andEqualTo("channelNo", "0");
        if (start == null) {
            criteria.andLessThan("timeId", stopTime);
        } else {
            String startTime = format.format(start);
            criteria.andBetween("timeId", startTime, stopTime);
        }
        List<CallStatistics> callStatistics = null;
        try {
            callStatistics = callStatisticsMapper.selectByExample(example);
        } catch (Exception e) {
            log.error("统计类ChartService[bulid-1]方法发生异常", e);
        }
        if (start == null) {
            try {
                if (callStatistics == null || callStatistics.size() < 1) {
                    return null;
                }
                start = format.parse(callStatistics.get(0).getTimeId());
            } catch (ParseException e) {
                log.error("统计类ChartService[bulid-2]方法发生异常", e);
            }
        }
        Map<String, Integer> map = new HashMap();
        for (long i = start.getTime(); i <= stop.getTime(); i += 60 * 60 * 24) {
            Date date = new Date(i);
            map.put(format.format(date), 0);
        }

        for (CallStatistics cs : callStatistics) {
            map.put(cs.getTimeId(), map.get(cs.getTimeId()) + cs.getNum());
        }
        return map;
    }

    public Integer signUseCount() {
        Example example = new Example(SignatureLog.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("uploadPdfStatus", 1);

        return requestLogService.selectCountByExample(example);
    }
}
